home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianNetDaemon.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
33KB
|
1,599 lines
/* ScianNetDaemon.c John R. Murray 1-19-92
*/
/* BSD_SIGS or SYSV_SIGS */
#ifdef PAUSE
#ifdef BSD_SIGS
#define _BSD_SIGNALS
#endif
#include <signal.h>
#include <stropts.h>
#endif /* def PAUSE */
#include "machine.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#if MACHINE == IRIS4D
#include <sys/prctl.h>
#endif
#if MACHINE == CONVEX
#include <time.h>
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <string.h>
#include <sys/times.h>
#include <sys/param.h>
#if MACHINE == CRAYYMP
#include <time.h>
#endif
#include "ScianNetDaemon.h"
#define PERROR
/* to avoid having to include lots of Scian include files */
#define ICONUNKNOWN 61
/* if you don't know how to pronounce "Daemon", listen to the beginning of
* the first song on the first side of _Locust Abortion Technician_ by
* the Butthole Surfers. Really loud. Really, really loud.
*/
#define true 1
#define false 0
/*Values for socketState*/
#define NOTLISTENING 0 /*Not even listening for a connection*/
#define LISTENING 1 /*Socket is listening for a connection*/
#define VALIDATING 2 /*Socket is connected*/
#define CONNECTED 3 /*Have gotten a good initial inquiry*/
#define TRANSFERRING 4 /*transferring connection to a scian process*/
#define NULLFILED -1
#define MYBUFSIZ 1024 /* size of local stream buffers */
#define IsMainConn(c) ((c) == mainConn)
/* #define IsMainConn(c) ((c)->sockNum == baseSocketNumber)
*/
int lasterror; /* tracks last system error */
#define ATTENTION_SPAN 30 /* start napping if < idle time */
#define DEFAULT_TIME_OUT (60 * 60) /* default timeout one hour */
typedef double Time;
/* timeOut = 0 means never time out */
Time timeOut = DEFAULT_TIME_OUT; /* no-activity timeout in seconds. */
struct tms timesBuffer; /* dummy for times() calls */
typedef struct ConnStruct {
int sockNum; /* socket number this one is connected to */
int template; /* socket template file descriptor */
int sock; /* socket file descriptor */
int state; /* state of socket */
int flags; /* informational bits */
char buf[MYBUFSIZ]; /* stream input buffer */
int bufi; /* index into stream buffer */
struct ConnStruct *next;
} *ConnPtr;
typedef struct SLStruct {
/* int sockNum; */
ConnPtr conn;
struct SLStruct *next;
} *SockListPtr;
typedef struct ORStruct {
unsigned long objectNum;
struct ORStruct *next;
int iconNum;
char objectName[1];
} *ObjRecPtr;
typedef struct PStruct {
int procNum;
int sockNum; /* process is listening on sockNum */
Time lastAccess;
ObjRecPtr objectList;
SockListPtr keepAdvised;
struct PStruct *next;
char procName[1];
} ProcessStruct, *ProcessPtr;
ProcessPtr processes;
char tempStr[MYBUFSIZ]; /* temp Str. */
#define ND_FLAGS_KEEPADVISED 0x01
#define ND_FLAGS_STREAMERROR 0x80
int socketBlockLength; /* how many socket numbers to try */
int baseSocketNumber; /* port number that connections come in on */
int lastPort; /* FindSocket keeps track of last socket number tried */
ConnPtr mainConn = (ConnPtr) 0; /* primary listener */
ConnPtr connList = (ConnPtr) 0; /* list of secondary connections */
int proto; /* protocol num. returned by getprotobyname()*/
#ifdef PAUSE
/* SIGIO signal handler */
int handlerCount = 0;
int oldHandlerCount = 0;
sigIOHandler()
{
++handlerCount;
#ifdef SYSV_SIGS
signal(SIGIO, sigIOHandler);
#endif
}
#endif
#ifdef ALARM
int alarmClock = 0;
sigAlrmHandler()
{
++alarmClock;
#ifdef SYSV_SIGS
signal(SIGALRM, sigAlrmHandler);
#endif
}
#endif
int writen(fd, cptr, nbytes)
int fd;
char *cptr;
int nbytes;
{
int nleft, nwritten;
nleft = nbytes;
while (nleft > 0)
{
nwritten = write(fd, cptr, nleft);
if (nwritten < 0)
{
perror("Uh-oh! writen");
return nwritten;
}
nleft -= nwritten;
cptr += nwritten;
}
}
/*NewConn: creates a new connection record from the stream associated with it*/
ConnPtr NewConn()
{
ConnPtr retVal;
retVal = malloc(sizeof(struct ConnStruct));
retVal -> bufi = 0;
retVal -> state = NOTLISTENING;
retVal -> flags = 0;
retVal -> sockNum = 0;
retVal -> next = (struct ConnStruct *) 0;
return retVal;
}
int FindSocket(c)
/* FindSocket looks for an open port. It returns 0 if successful, -1
* if failed. If the port number in the connection record (c->sockNum) is
* non-zero, FindSocket tries to open that port, and fails if it's not
* available. If c->sockNum is zero, FindSocket will search the possible
* port numbers until it successfully binds one.
*/
ConnPtr c;
{
struct sockaddr_in templateAddr; /*Socket template for listening*/
int any_port;
int first_tried;
int status;
any_port = true;
/* sanity check */
if (c->state != NOTLISTENING)
{
fprintf(stderr, "FindSocket sanity check! Bad state %d\n", c->state);
return -1;
}
/* initialize */
if (c->sockNum != 0)
{
templateAddr . sin_port = htons((u_short) c->sockNum);
first_tried = c->sockNum;
any_port = false;
}
else
{
if (++lastPort >= baseSocketNumber + socketBlockLength)
lastPort = baseSocketNumber + 1;
templateAddr . sin_port = htons((u_short) lastPort);
first_tried = lastPort;
c->sockNum = lastPort;
}
templateAddr . sin_family = PF_INET;
templateAddr . sin_addr.s_addr = INADDR_ANY;
c->template = socket(PF_INET, SOCK_STREAM, proto);
if (c->template < 0)
{
{
#ifdef PERROR
perror("socket() in FindSocket");
#endif
if (any_port) c->sockNum = 0;
return -1;
}
}
#ifdef PAUSE
/* ioctl(c->template, I_SETSIG, S_INPUT); */
fcntl(c->template, F_SETOWN, getpid());
fcntl(c->template, F_SETFL, fcntl(c->template, F_GETFL) | FASYNC);
if (!(fcntl(c->template, F_GETFL) & FASYNC))
fprintf(stderr, "template flag not set, Bub!\n");
#endif
status = -1;
while (status < 0)
{
#ifdef DEBUG
fprintf(stderr, "trying to bind socket %d\n", ntohs(templateAddr.sin_port));
#endif
status = bind(c->template, &templateAddr, sizeof(templateAddr));
if (status >= 0)
{
/*Name was bound OK*/
/*Set socket to be non blocking*/
#if CRAYYMP
fcntl(c->template, F_SETFL,
fcntl(c->template, F_GETFL) | O_NDELAY);
fcntl(c->template, F_SETFL,
fcntl(c->template, F_GETFL) | O_NONBLOCK);
#else
fcntl(c->template, F_SETFL,
fcntl(c->template, F_GETFL) | FNDELAY);
#endif
/*Listen for a maximum of 5 connections*/
if (listen(c->template, 5) < 0)
{
#ifdef PERROR
perror("listen() in FindSocket");
#endif
if (any_port) c->sockNum = 0;
close (c->template); c->template = -1;
return -1;
}
}
else
{
if (any_port && (errno == EADDRINUSE))
{
if (++lastPort >= baseSocketNumber+socketBlockLength)
lastPort = baseSocketNumber + 1;
templateAddr . sin_port = htons((u_short) lastPort);
c->sockNum = lastPort;
if (lastPort == first_tried)
{
/*went all the way through the block without finding one*/
fprintf(stderr, "No sockets open!\n");
if (any_port) c->sockNum = 0;
close (c->template); c->template = -1;
return -1;
}
}
else
{
#ifdef PERROR
perror("bind() call failed in FindSocket");
#endif
if (any_port) c->sockNum = 0;
close (c->template); c->template = -1;
return -1;
}
}
}
return 0;
}
void CloseSocket(c)
ConnPtr c;
{
if (c->sock >= 0)
{
close(c->sock); c->sock = -1;
}
if (c->template >= 0)
{
close(c->template); c->template = -1;
}
c->bufi = 0;
c->state = NOTLISTENING;
}
void CloseAll()
{
ConnPtr runner;
CloseSocket(mainConn);
runner = connList;
while(runner)
{
CloseSocket(runner);
runner = runner->next;
}
}
void AddConnectionRecord(c)
ConnPtr c;
{
c -> next = connList;
connList = c;
}
/* using the socket number, find the connection record for that socket */
ConnPtr FindConnectionRecord(num)
int num;
{
ConnPtr runner;
runner = connList;
while(runner)
{
if (runner -> sockNum == num)
{
return runner;
}
runner = runner -> next;
}
return (ConnPtr) 0;
}
void DeleteConnectionRecord(c)
ConnPtr c;
{
ConnPtr *runner;
runner = &connList;
while (*runner)
{
if ((*runner) == c)
{
while (DoDeferredMessage()) /* What a hack! clear deferred msgs */
;
(*runner) = (*runner) -> next;
free (c);
return;
}
runner = &((*runner) -> next);
}
}
int strcmp2(s1, s2)
char s1[], s2[];
/*Compares s1 and s2 without regard to case*/
{
int k;
for (k = 0; s1[k]; ++k)
{
if (toupper(s1[k]) < toupper(s2[k])) return -k - 1;
if (toupper(s1[k]) > toupper(s2[k])) return k + 1;
}
return s2[k] ? -k - 1 : 0;
}
int strncmp2(s1, s2, n)
char s1[], s2[];
int n;
/*Compares s1 and s2 up to character <n> without regard to case*/
{
int k;
for (k = 0; k<n && s1[k]; ++k)
{
if (toupper(s1[k]) < toupper(s2[k])) return -k - 1;
if (toupper(s1[k]) > toupper(s2[k])) return k + 1;
}
return k<n && s2[k] ? -k - 1 : 0;
}
char *nbfgets(c)
ConnPtr c;
{
char *retVal;
retVal = (char *) 0;
errno = 0;
while (!retVal && (1 == read(c -> sock, &(c->buf[c->bufi]),1)))
{
#ifdef DEBUG
if (isprint(c->buf[c->bufi]))
fprintf(stderr, "...(%c)\n", c->buf[c->bufi]);
else
fprintf(stderr, "---(\\%o)\n", c->buf[c->bufi]);
#endif
if ((c->buf[c->bufi] == '\n' && (c->bufi==0 || c->buf[c->bufi-1]!='\\'))
|| c->buf[c->bufi] == '\0')
{
c->buf[++(c->bufi)] = '\0';
c->bufi = 0;
retVal = c->buf;
}
else
{
c->bufi++;
}
if (errno)
{
if (errno != lasterror)
{
fprintf(stderr, "error #%d in socket descriptor\n", errno, c->sock);
#ifdef PERROR
perror("nbfgets");
#endif
lasterror = errno;
}
if ((errno != EWOULDBLOCK) && (errno != EAGAIN) && (errno != EINTR))
{
fprintf(stderr, "Yanking someone's connection\n");
if (errno == EBADF)
{
close(c -> sock);
}
else
{
CloseSocket(c);
}
DeleteConnectionRecord(c);
}
errno = 0;
}
}
return retVal;
}
char *CopyScianString(l, s)
char *l, *s;
{
char *lPtr, *sPtr;
int notdone;
lPtr = l;
sPtr = s;
/* skip whitespace */
while (isspace(*sPtr))
{
++sPtr;
}
notdone = true;
while(notdone && sPtr - s < MYBUFSIZ)
{
switch (*sPtr)
{
case ' ': case '\n': case '\t': case '\0': case '\r':
notdone = false;
*lPtr = '\0';
break;
case '\\':
*lPtr++ = *sPtr;
++sPtr;
*lPtr++ = *sPtr;
break;
default:
*lPtr++ = *sPtr;
break;
}
if (notdone)
++sPtr;
}
if (lPtr == l)
{
/* didn't write anything! */
return (char *) 0;
}
return sPtr;
}
/* write a string to a socket. Force a \n onto the end */
void PutSock(conn, s)
ConnPtr conn;
char *s;
{
int tmp, sofar;
if (conn->sock < 0)
{
fprintf(stderr, "tried to write to bad file descriptor!\n");
return;
}
if (conn -> state != CONNECTED)
{
fprintf(stderr, "write with socket state = %d\n", conn -> state);
return;
}
errno = 0;
writen(conn -> sock, s, strlen(s));
if (errno)
{
#ifdef PERROR
perror("PutSock");
#endif
conn -> flags = conn -> flags | ND_FLAGS_STREAMERROR;
errno = 0;
}
}
typedef struct Message {
/* int sockNum; */
ConnPtr conn;
struct Message *next;
char s;
} *MessagePtr;
MessagePtr messageList = (MessagePtr) 0;
void DeferMessage(c, s)
/* int cNum; */
ConnPtr c;
char *s;
{
MessagePtr tmp, *runner;
/* allocate space for the structure (-1 byte) plus the string (+1 byte) */
tmp = malloc(sizeof(struct Message) + strlen(s));
tmp->next = (struct Message *) 0;
tmp->conn = c;
strcpy(&(tmp->s), s);
/*stick message on the end of the list */
runner = &messageList;
while(*runner)
runner = &((*runner)->next);
*runner = tmp;
}
int DoDeferredMessage()
{
MessagePtr msg;
if (!messageList)
return false;
msg = messageList;
messageList = messageList -> next;
PutSock(msg -> conn, &(msg -> s));
return true;
}
Time Clock()
{
#if MACHINE == IRIS4D
return ((double) times(×Buffer)) / HZ;
#else
#if MACHINE == CRAYYMP
return ((double) times(×Buffer)) / CLK_TCK;
#else
return ((double) times(×Buffer)) / CLK_TCK;
#endif
#endif
}
ProcessPtr FindProcess(num)
int num;
{
ProcessPtr tmp;
tmp = processes;
while (tmp)
{
if (tmp->procNum == num)
{
return tmp;
}
tmp = tmp->next;
}
return (ProcessPtr) 0;
}
int DeleteProcess(num)
int num;
{
ProcessPtr *runner, tmp;
ObjRecPtr objRunner;
SockListPtr sockRunner;
runner = &processes;
while (*runner)
{
if ((*runner)->procNum == num)
{
tmp = *runner;
*runner = (*runner) -> next;
objRunner = tmp -> objectList;
while (objRunner)
{
free (objRunner);
objRunner = objRunner -> next;
}
sockRunner = tmp -> keepAdvised;
while (sockRunner)
{
free (sockRunner);
sockRunner = sockRunner -> next;
}
free (tmp);
return 0;
}
runner = &((*runner)->next);
}
#ifdef DEBUG
fprintf(stderr, "DeleteProcess: process number %d does not exist\n", num);
#endif
return -1;
}
int AddProcess(num, sockNum, name)
int num;
int sockNum;
char *name;
{
ProcessPtr procPtr;
if (FindProcess(num))
{
/* it's already there */
#ifdef DEBUG
fprintf(stderr, "Tried to duplicate process number\n");
#endif
return -1;
}
/* it wasn't already there, add new process. */
procPtr = (ProcessPtr) malloc(sizeof(ProcessStruct)+(name?strlen(name):0));
procPtr -> procNum = num;
procPtr -> sockNum = sockNum;
procPtr -> lastAccess = Clock();
procPtr -> next = processes;
procPtr -> objectList = (ObjRecPtr) 0;
procPtr -> keepAdvised = (SockListPtr) 0;
if (name)
strcpy(procPtr -> procName, name);
else
procPtr -> procName[0] = '\0';
processes = procPtr;
#ifdef DEBUG
fprintf(stderr, "added process #%d\n", num);
#endif
return 0;
}
ObjRecPtr FindObject(procNum, objNum)
int procNum;
unsigned long objNum;
{
ProcessPtr procPtr;
ObjRecPtr runner;
if (!(procPtr = FindProcess(procNum)))
{
return (ObjRecPtr) 0;
}
runner = procPtr -> objectList;
while (runner)
{
if (runner -> objectNum == objNum)
{
return runner;
}
runner = runner -> next;
}
return (ObjRecPtr) 0;
}
int DeleteObject(procNum, objNum)
int procNum;
unsigned long objNum;
{
ProcessPtr procPtr;
ObjRecPtr *runner;
if (!(procPtr = FindProcess(procNum)))
{
return -1;
}
runner = &(procPtr -> objectList);
while (*runner)
{
if ((*runner) -> objectNum == objNum)
{
ObjRecPtr tmp;
tmp = *runner;
*runner = (*runner) -> next;
free(tmp);
return 0;
}
runner = &((*runner) -> next);
}
return -1;
}
int AddObject(procNum, objNum, iconNum, objName)
int procNum;
unsigned long objNum;
int iconNum;
char *objName;
{
ProcessPtr procPtr;
ObjRecPtr tmp;
if (!(procPtr = FindProcess(procNum)))
{
return -1;
}
if (FindObject(procNum, objNum))
{
/* object already existed? */
return -1;
}
tmp = malloc(sizeof(struct ORStruct) + (objName ? strlen(objName) : 0));
tmp -> objectNum = objNum;
tmp -> iconNum = iconNum;
strcpy(tmp -> objectName, objName);
tmp -> next = procPtr -> objectList;
procPtr -> objectList = tmp;
return 0;
}
#if 0
static u_short SocketPort(c)
/*Returns the port for the socket*/
ConnPtr c;
{
return htons((u_short) c -> sockNum);
}
#endif
void InterpretSocketCommand(c, s)
ConnPtr c;
char *s;
{
int procNum;
unsigned long objNum;
int objIconNum;
ProcessPtr procPtr;
ObjRecPtr objPtr;
SockListPtr sockPtr;
char procName[MYBUFSIZ], objName[MYBUFSIZ];
char *cPtr;
int chri;
if (4 != ND_CMD_STR_LENGTH)
{
fprintf(stderr, "ScianNetDaemon: Internal Error!\n");
}
if (strlen(s) < ND_CMD_STR_LENGTH)
{
#ifdef DEBUG
fprintf(stderr, "ScianNetDaemon: socket command format error\n");
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (0 == strncmp2(s, ND_REG_PROCESS, ND_CMD_STR_LENGTH))
{
ConnPtr runner;
int sockNum;
/* should be a process number following */
if (2 != sscanf (s + 4, "%d%d%n", &procNum, &sockNum, &chri))
{
#ifdef DEBUG
fprintf(stderr, "Error: no process number\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (!CopyScianString(procName, s + 4 + chri))
{
sprintf(procName, "proc%d", procNum);
}
else if (procName[strlen(procName) - 1] == '\\')
{
/* more string on the next line */
}
if(AddProcess(procNum, sockNum, procName))
{
#ifdef DEBUG
fprintf(stderr, "process #%d already existed\n", procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
runner = connList;
sprintf(tempStr, "%s %d %s\n", ND_INFO_LIVE_PROCESS,
sockNum, procName);
while (runner)
{
if (runner -> flags & ND_FLAGS_KEEPADVISED)
{
DeferMessage(runner, tempStr);
}
runner = runner -> next;
}
}
else if (0 == strncmp2(s, ND_UNREG_PROCESS, ND_CMD_STR_LENGTH))
{
/* should be a process number following */
if (1 != sscanf (s + 4, "%d", &procNum))
{
#ifdef DEBUG
fprintf(stderr, "Error: no process number\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (procPtr = FindProcess(procNum))
{
sprintf(tempStr, "%s %d %s\n", ND_INFO_DEAD_PROCESS,
procPtr -> sockNum, procPtr -> procName);
}
if (DeleteProcess(procNum) != -1)
{
ConnPtr runner;
runner = connList;
while (runner)
{
if (runner -> flags & ND_FLAGS_KEEPADVISED)
{
DeferMessage(runner, tempStr);
}
runner = runner -> next;
}
}
}
else if (0 == strncmp2(s, ND_INQ_PROCESS, ND_CMD_STR_LENGTH))
{
/* should be etc., etc., etc.. */
if (1 != sscanf (s + 4, "%d", &procNum))
{
#ifdef DEBUG
fprintf(stderr, "Error: no process number\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (!(procPtr = FindProcess(procNum)))
{
#ifdef DEBUG
fprintf(stderr, "Error: Process #%d not found\n", procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
sprintf(tempStr, "%s %d %s\n", ND_INFO_LIVE_PROCESS, procPtr -> sockNum,
procPtr -> procName);
DeferMessage(c, tempStr);
}
else if (0 == strncmp2(s, ND_LIST_PROCESSES, ND_CMD_STR_LENGTH))
{
ProcessPtr runner;
runner = processes;
while (runner)
{
sprintf(tempStr, "%s %d %s\n", ND_INFO_LIVE_PROCESS,
runner -> sockNum, runner -> procName);
DeferMessage(c, tempStr);
runner = runner -> next;
}
}
else if (0 == strncmp2(s, ND_UPDATE_PROCESSES, ND_CMD_STR_LENGTH))
{
ProcessPtr runner;
runner = processes;
while (runner)
{
sprintf(tempStr, "%s %d %s\n", ND_INFO_LIVE_PROCESS,
runner -> sockNum, runner -> procName);
DeferMessage(c, tempStr);
runner = runner -> next;
}
c -> flags = c -> flags | ND_FLAGS_KEEPADVISED;
}
else if (0 == strncmp2(s, ND_NOT_UPDATE_PROCESSES, ND_CMD_STR_LENGTH))
{
c -> flags = c -> flags & ~ND_FLAGS_KEEPADVISED;
}
else if (0 == strncmp2(s, ND_REG_OBJECT, ND_CMD_STR_LENGTH))
{
SockListPtr runner;
/* should be a process number and object number following */
if (2 != sscanf (s + 4, "%d%d%n", &procNum, &objNum, &chri))
{
#ifdef DEBUG
fprintf(stderr, "Error: process and object numbers expected\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (!(cPtr = CopyScianString(objName, s + 4 + chri)))
{
sprintf(objName, "obj%d", objNum);
}
if (cPtr)
{
if (1 != sscanf (cPtr, "%d", &objIconNum))
{
objIconNum = ICONUNKNOWN;
}
}
else
{
objIconNum = ICONUNKNOWN;
}
if (!(procPtr = FindProcess(procNum)))
{
#ifdef DEBUG
fprintf (stderr, "no process #%d\n", procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if(-1 == AddObject(procNum, objNum, objIconNum, objName))
{
#ifdef DEBUG
fprintf(stderr, "Couldn't add object %ld to process %d\n", objNum, procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
runner = procPtr -> keepAdvised;
sprintf(tempStr, "%s %d %d %s %d\n", ND_INFO_LIVE_OBJECT,
procNum, objNum, objName, objIconNum);
while (runner)
{
DeferMessage(runner -> conn, tempStr);
runner = runner -> next;
}
}
else if (0 == strncmp2(s, ND_UNREG_OBJECT, ND_CMD_STR_LENGTH))
{
/* should be a process number and object number following */
if (2 != sscanf (s + 4, "%d%d", &procNum, &objNum))
{
#ifdef DEBUG
fprintf(stderr, "Error: process and object numbers expected\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (!(procPtr = FindProcess(procNum)))
{
#ifdef DEBUG
fprintf (stderr, "no process #%d\n", procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if(-1 == DeleteObject(procNum, objNum))
{
#ifdef DEBUG
fprintf(stderr, "Error deleting object %ld from process %d\n", objNum, procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
{
SockListPtr runner;
runner = procPtr -> keepAdvised;
sprintf(tempStr, "%s %d %d\n", ND_INFO_DEAD_OBJECT, procNum, objNum);
while (runner)
{
DeferMessage(runner -> conn, tempStr);
runner = runner -> next;
}
}
}
else if (0 == strncmp2(s, ND_INQ_OBJECT, ND_CMD_STR_LENGTH))
{
/* should be a process number and object number following */
if (2 != sscanf (s + 4, "%d%d", &procNum, &objNum))
{
#ifdef DEBUG
fprintf(stderr, "Error: process and object numbers expected\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (!(procPtr = FindProcess(procNum)))
{
#ifdef DEBUG
fprintf (stderr, "no process #%d\n", procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if(!(objPtr = FindObject(procNum, objNum)))
{
#ifdef DEBUG
fprintf(stderr, "Couldn't find object %ld in process %d\n",
objNum, procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
else
{
sprintf(tempStr, "%s %d %d %s %d\n", ND_INFO_LIVE_OBJECT,
procNum, objNum, objPtr -> objectName, objPtr -> iconNum);
DeferMessage(c, tempStr);
}
}
else if (0 == strncmp2(s, ND_LIST_OBJECTS, ND_CMD_STR_LENGTH))
{
/* should be a process number number following */
if (1 != sscanf (s + 4, "%d", &procNum))
{
#ifdef DEBUG
fprintf(stderr, "Error: process number expected\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (!(procPtr = FindProcess(procNum)))
{
#ifdef DEBUG
fprintf (stderr, "no process #%d\n", procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
/* advise of objects that are already listed */
objPtr = procPtr -> objectList;
while (objPtr)
{
sprintf(tempStr, "%s %d %d %s %d\n", ND_INFO_LIVE_OBJECT, procNum,
objPtr -> objectNum, objPtr -> objectName, objPtr -> iconNum);
DeferMessage(c, tempStr);
objPtr = objPtr -> next;
}
}
else if (0 == strncmp2(s, ND_UPDATE_OBJECTS, ND_CMD_STR_LENGTH))
{
/* should be a process number number following */
if (1 != sscanf (s + 4, "%d", &procNum))
{
#ifdef DEBUG
fprintf(stderr, "Error: process number expected\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (!(procPtr = FindProcess(procNum)))
{
#ifdef DEBUG
fprintf (stderr, "no process #%d\n", procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
sockPtr = malloc(sizeof(struct SLStruct));
sockPtr -> conn = c;
sockPtr -> next = procPtr -> keepAdvised;
procPtr -> keepAdvised = sockPtr;
/* advise of objects that are already listed */
objPtr = procPtr -> objectList;
while (objPtr)
{
sprintf(tempStr, "%s %d %d %s %d\n", ND_INFO_LIVE_OBJECT, procNum,
objPtr -> objectNum, objPtr -> objectName, objPtr -> iconNum);
DeferMessage(c, tempStr);
objPtr = objPtr -> next;
}
}
else if (0 == strncmp2(s, ND_NOT_UPDATE_OBJECTS, ND_CMD_STR_LENGTH))
{
SockListPtr *runner;
/* should be a process number number following */
if (1 != sscanf (s + 4, "%d", &procNum))
{
#ifdef DEBUG
fprintf(stderr, "Error: process number expected\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
if (!(procPtr = FindProcess(procNum)))
{
#ifdef DEBUG
fprintf (stderr, "no process #%d\n", procNum);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
runner = &(procPtr -> keepAdvised);
while (*runner)
{
if ((*runner) -> conn == c)
{
SockListPtr tmp;
tmp = *runner;
*runner = (*runner) -> next;
free (tmp);
break;
}
runner = &((*runner) -> next);
}
}
else if (0 == strncmp2(s, ND_CLOSE, ND_CMD_STR_LENGTH))
{
if (IsMainConn(c))
{
close(c->sock); c->sock = -1;
c->state = LISTENING;
}
else
{
CloseSocket(c);
DeleteConnectionRecord(c);
}
}
else if (0 == strncmp2(s, ND_EXIT, ND_CMD_STR_LENGTH))
{
#ifdef DEBUG
fprintf(stderr, "got exit directive, byebye\n");
#endif
CloseAll();
exit (0);
}
else
{
#ifdef DEBUG
fprintf(stderr, "Error: unparseable\n%s\n", s);
#endif
sprintf(tempStr, "%s\n", ND_ERROR);
PutSock(c, tempStr);
return;
}
}
#define COMMAND_SIZ 256
int IdleSocket(c)
ConnPtr c;
/* My version of idling the sockets */
{
struct sockaddr_in inSocketAddr;
int inSocket;
int tmp;
ConnPtr tmpConn;
/* temporary? */
char *tmpPtr;
if (!c)
{
fprintf(stderr, "Null Connection pointer!\n");
return false;
}
switch (c->state)
{
case NOTLISTENING:
if (FindSocket(c) < 0)
{
#ifdef DEBUG
fprintf(stderr, "FindSocket() failed!\n");
#endif
if (IsMainConn(c)) sleep(1);
return false;
}
fprintf(stderr, "connected\n");
c->state = LISTENING;
break;
case LISTENING:
/* waiting for a phone call */
c->sock = accept(c->template, (struct sockaddr *) 0, (int *) 0);
if (c->sock != -1)
{
#ifdef PAUSE
/* ioctl(c->sock, I_SETSIG, S_INPUT); */
fcntl(c->sock, F_SETOWN, getpid());
fcntl(c->sock, F_SETFL,
fcntl(c->sock, F_GETFL) | FASYNC);
#endif
/* set up main connection */
/*
if (IsMainConn(c))
{
c->state = VALIDATING;
}
else
{
c->state = CONNECTED;
sprintf(tempStr, "%s %s\n", ND_INFO_VERSION,
ND_NET_DAEMON_VERSION);
DeferMessage(c, tempStr);
}
*/
c -> state = VALIDATING;
/* version message moved down to case VALIDATING */
}
else
{
return false;
}
break;
case VALIDATING:
/* one ringy dingy... */
if (tmpPtr = nbfgets(c))
{
#ifdef DEBUG
fprintf(stderr, "tmpPtr = %s\n", tmpPtr);
#endif
if (0 != strncmp2(tmpPtr, ND_PASSWORD, ND_CMD_STR_LENGTH))
{
return false;
}
fprintf(stderr, "accepted and validated connection\n");
tmpConn = NewConn();
AddConnectionRecord(tmpConn);
tmpConn -> state = CONNECTED;
tmpConn -> sock = c -> sock;
sprintf(tempStr, "%s %s\n", ND_INFO_VERSION,
ND_NET_DAEMON_VERSION);
DeferMessage(tmpConn, tempStr);
c -> sock = -1;
c->state = LISTENING;
return true;
}
else
{
return false;
}
break;
case CONNECTED:
if (tmpPtr = nbfgets(c))
{
#ifdef DEBUG
fprintf(stderr, "tmpPtr = %x, *tmpPtr: %s\n", tmpPtr, tmpPtr);
#endif
InterpretSocketCommand(c, tmpPtr);
}
else
{
return false;
}
break;
case TRANSFERRING:
/* forwarding your call to the appropriate party */
break;
}
return true;
}
/* ConnPtr connTracker = (ConnPtr) 0; */
Time lastActionTime;
void IdleAllSockets()
{
ConnPtr connTracker;
int didSomething = 0;
didSomething += IdleSocket(mainConn);
/*
if (!connTracker)
{
connTracker = connList;
}
*/
connTracker = connList;
/* if */ while (connTracker)
{
didSomething += IdleSocket(connTracker);
connTracker = connTracker -> next;
}
if (!didSomething)
{
didSomething += DoDeferredMessage();
}
if (didSomething)
{
lastActionTime = Clock();
}
/* go out to lunch if no activity in the last ATTENTION_SPAN secs*/
if (Clock() > lastActionTime + ATTENTION_SPAN && !didSomething)
{
#ifdef PAUSE
sigblock(sigmask(SIGIO));
sigpause(sigmask(SIGIO));
fprintf(stderr, "handler was called %d times\n", handlerCount - oldHandlerCount);
oldHandlerCount = handlerCount;
sigsetmask(0);
#else
sleep(1);
#endif
}
if (timeOut > 0.0 && Clock() > lastActionTime + timeOut && !didSomething)
{
/* we've been idle for too long, time to go home */
fprintf(stderr, "No activity for %d seconds, NetDaemon exiting\n",
(int) (Clock() - lastActionTime));
exit(0);
}
}
void CommandLineError(name)
char *name;
{
fprintf(stderr, "error on command line\n");
fprintf(stderr, "usage: %s [-t <timeout>] [-s <socketnumber>] [-l <blocklength>]\n", name);
exit (-1);
}
ParseArgs(argc, argv)
int argc;
char *argv[1];
{
int i;
char *cPtr;
socketBlockLength = ND_SOCKET_BLOCK_LENGTH; /*may be overridden */
baseSocketNumber = ND_BASE_SOCKET_NUMBER; /*may be overridden on cmd line*/
for (i = 1; i < argc; ++i)
{
cPtr = argv[i];
if (*cPtr == '-')
{
switch(*++cPtr)
{
case 't':
if (1 != sscanf(++cPtr, "%lf", &timeOut))
{
if ((i + 1 >= argc) || (1 != sscanf(argv[i+1],
"%lf", &timeOut)))
{
fprintf(stderr, "integer expected after -t\n");
CommandLineError(argv[0]);
}
else
{
++i;
}
}
break;
case 's':
if (1 != sscanf(++cPtr, "%d", &baseSocketNumber))
{
if ((i + 1 >= argc) || (1 != sscanf(argv[i+1],
"%d", &baseSocketNumber)))
{
fprintf(stderr, "integer expected after -s\n");
CommandLineError(argv[0]);
}
else
{
++i;
}
}
break;
case 'l':
if (1 != sscanf(++cPtr, "%d", &socketBlockLength))
{
if ((i + 1 >= argc) || (1 != sscanf(argv[i+1],
"%d", &socketBlockLength)))
{
fprintf(stderr, "integer expected after -l\n");
CommandLineError(argv[0]);
}
else
{
++i;
}
}
break;
default:
fprintf(stderr, "unexpected argument\n");
CommandLineError(argv[0]);
break;
}
}
else
{
fprintf(stderr, "error in argument\n");
CommandLineError(argv[0]);
}
}
}
void SanityCheck()
{
ConnPtr runner1, runner2;
runner1 = connList;
while (runner1)
{
runner2 = runner1 -> next;
while (runner2)
{
if (runner1 -> sock == runner2 -> sock)
{
fprintf(stderr, "shared file descriptor! %d.\n", runner1 -> sock);
}
}
}
}
#define SANITYCHECKINTERVAL 5
main(argc, argv)
int argc;
char *argv[1];
{
Time lastSanityCheck;
#ifdef PAUSE
#ifdef BSD_SIGS
struct sigvec sv,osv;
sv.sv_handler = sigIOHandler; /* pointer to routine. */
sv.sv_mask = 0; /* no additional signals masked */
sv.sv_flags = SV_INTERRUPT; /* no restarted system calls */
sigvec(SIGIO,&sv,&osv);
#else
#ifdef SYSV_SIGS
signal(SIGIO, sigIOHandler);
#else
Yer up shits creek, bud!;
#endif /* def SYSV_SIGS */
#endif /* def BSD_SIGS */
#endif /* def PAUSE */
#ifdef ALARM
#ifdef SYSV_SIGS
signal(SIGALRM, sigAlrmHandler);
#else
#ifdef BSD_SIGS
sv.sv_handler = sigAlrmHandler; /* pointer to routine. */
sv.sv_mask = 0; /* no additional signals masked */
sv.sv_flags = SV_INTERRUPT; /* no restarted system calls */
sigvec(SIGALRM,&sv,&osv);
#else
Need BSD_SIGS or SYSV_SIGS defined!
#endif /* def BSD_SIGS */
#endif /* def SYSV_SIGS */
#endif /* def ALARM */
ParseArgs(argc, argv);
lastPort = baseSocketNumber;
lastActionTime = Clock();
mainConn = NewConn();
mainConn -> sockNum = baseSocketNumber;
proto = getprotobyname("tcp") -> p_proto;
for (;;)
{
IdleAllSockets();
#ifdef ALARM
if (alarmClock)
{
CloseAll();
exit(0);
}
#endif /* def ALARM */
if (lastSanityCheck + SANITYCHECKINTERVAL > Clock())
{
SanityCheck();
}
}
}